#include "copierhandler.h"
#include "drivecontroler.h"
#include "QUuid"

CopierHandler::CopierHandler(QString letter,const char *source,QString to,QString finalPath, QObject *parent) :
    QObject(parent)
{
    _progress = 0;
    if(!letter.contains(':'))
        letter +=":";
    _driveLetter = letter;
    _tempPath = to;
    _destinationPath = finalPath;
    _source = source;
    this->_copier = new FolderCopierThread(letter,source,_tempPath);
    QObject::connect(this->_copier, SIGNAL(copyFinished(QString,QString,QString,bool)),
            this, SLOT(copyFinished(QString,QString,QString,bool)));

    QObject::connect(this->_copier, SIGNAL(copyCanceled(QString,QString,QString,bool)),
            this, SLOT(copyCanceled(QString,QString,QString,bool)));

    timer.setInterval(30*1000);
    connect(&timer, SIGNAL(timeout()), this, SLOT(checkProgress()));
    _proc = NULL;
}
CopierHandler::~CopierHandler()
{
    qDebug() << "CopierHandler::~CopierHandler()";
    if(this->_copier!=NULL)
    {
        qDebug() << "this->_copier->wait()";
        this->_copier->terminate();
        qDebug() << "delete this->_copier";
        delete this->_copier;
        qDebug() << "this->_copier=NULL";
        this->_copier=NULL;
    }
    if(_proc!=NULL)
    {
        qDebug() << "_proc->kill();";
        if (_proc->state()!=QProcess::NotRunning)
        {
            qDebug() << "_proc->state(): "<<_proc->state();
            _proc->kill();
            qDebug() << "_proc->kill();";
        }
        delete _proc;
    }

}

void CopierHandler::stopCopyDisc()
{
    qDebug() << "void CopierHandler::stopCopyDisc()";
    this->_copier->stopCopy();
}

void CopierHandler::startCopyDisc()
{

    timer.start();
    this->_copier->setId(_discData.getId());
    this->_copier->setDiscId(_discData.getDiscId());
    this->_copier->setDriveLetter(_driveLetter);
    this->_copier->setPathTo(_tempPath);
    QString uuid = QUuid::createUuid();
    uuid = uuid.remove('{');
    uuid = uuid.remove('}');
    this->_copier->setTitleId(uuid);
    this->calculateTotalSize(_source);
    this->startRobocopy(uuid,_driveLetter+_source,_discData.getDiscId(),_parentalControl);
    //this->_copier->startCopy(uuid,_discData.getParentalControl());

}
void CopierHandler::calculateTotalSize(const QString &path)
{
    QDir directory(this->_driveLetter+path);

    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Dirs))
    {
        if(info.isDir())
        {
            QString folderName = info.fileName();
            if(info.fileName()!="."&&info.fileName()!="..")
            {
                QString sourcePath = path + "/" + folderName;
                this->calculateTotalSize(sourcePath);
            }

        }
    }
    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Files))
    {
        if(info.isFile())
        {
            this->_totalSize+= info.size();
            qDebug() << "Adding: "<<info.size();
            qDebug() << "Total size: "<<this->_totalSize;
        }
    }
}
void CopierHandler::calculateAlreadyCopied(const QString &path)
{
    qDebug() << "CopierHandler::calculateAlreadyCopied(const QString &path):"<<path;
    QDir directory(path);

    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Dirs))
    {
        if(info.isDir())
        {
            QString folderName = info.fileName();
            if(info.fileName()!="."&&info.fileName()!="..")
            {
                QString sourcePath = path + "/" + folderName;
                qDebug() << "Folder:"<<sourcePath;
                this->calculateAlreadyCopied(sourcePath);
            }

        }
    }
    qDebug() << "Folder:"<<path;
    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Files))
    {
        qDebug() << "File:"<<info.fileName();
        if(info.isFile())
        {
            this->_copiedSize+= info.size();
            qDebug() << "Adding: "<<info.size();
            qDebug() << "Copied size: "<<this->_copiedSize;
        }
    }
}
void CopierHandler::removeFolder(const QString &path)
{
    qDebug() << "CopierHandler::removeFolder(const QString &path):"<<path;
    QDir directory(path);
    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Dirs))
    {
        if(info.isDir())
        {
            QString folderName = info.fileName();
            if(info.fileName()!="."&&info.fileName()!="..")
            {
                qDebug() << "folder: " << folderName;
                QString targetPath = path + "/" + folderName;
                this->removeFolder(targetPath);
            }

        }
    }
    qDebug() << "files:";
    foreach(const QFileInfo &info, directory.entryInfoList(QDir::Files))
    {
        if(info.isFile())
        {
            QFile file(info.absoluteFilePath());
            file.setPermissions(QFile::ReadOther | QFile::WriteOther);

            if(file.remove())
            {
                qDebug() << "removed file: "<<info.absoluteFilePath();
            }
            else
            {
                qDebug() << "error removing file: "<<info.absoluteFilePath();
            }
        }
    }
    QDir parentDstDir(path);
    QFile::setPermissions(path,QFile::ReadOther | QFile::WriteOther);
    if (!parentDstDir.rmdir(path))
    {
        qDebug() << "Error removing folder: "<<path;
    }
}

void CopierHandler::startCopyDisc(DiscData discData)
{

    timer.start();
    this->_copier->setId(discData.getId());
    QListIterator<Disc> it = discData.discTitle.discs;
    Disc disc;
    if(it.hasNext())
        disc = it.next();
    this->_copier->setDiscId(disc.discIdSideA);
    QString uuid = QUuid::createUuid();
    uuid = uuid.remove('{');
    uuid = uuid.remove('}');
    this->_copier->setTitleId(uuid);
    this->calculateTotalSize(_source);
    this->startRobocopy(uuid,_driveLetter+_source,discData.getDiscId(),discData.parentalControl);
    //this->_copier->startCopy(uuid,discData.getParentalControl());
}

void CopierHandler::copyDisc()
{
    startCopyDisc();
    //emit readyToCopy();
}

void CopierHandler::setDiscDataList(QList<DiscData> discData)
{
    _discDataList = discData;
    emit readyToCopy();
}
void CopierHandler::setDiscData(DiscData discData)
{
    _discData = discData;
    emit readyToCopy();
}
void CopierHandler::changeLetter(QString letter)
{
    qDebug() << "void CopierHandler::changeLetter(QString): "<<letter;
    if(!letter.contains(':'))
        letter +=":";

    _driveLetter = letter;
}

void CopierHandler::changeFinalFolder(QString path)
{
    qDebug() << "void CopierHandler::changeFinalFolder(QString path): "<<path;

    _destinationPath = path;
}

void CopierHandler::changeTempFolder(QString path)
{
    qDebug() << "void CopierHandler::changeTempFolder(QString path): "<<path;

    _tempPath = path;
}

void CopierHandler::checkProgress()
{
    qDebug() << "CopierHandler::checkProgress()";
    this->_copiedSize = 0;
    _progress= 0;

    this->calculateAlreadyCopied(_destinationPath+ "\\" + this->_copier->getValidFolderName());
    if(_totalSize!=0)
        _progress= (int)(((double)_copiedSize/(double)_totalSize)*100);

    if(this->_copier!=NULL)
    {
        qDebug() << "Progress: "<<_progress<<"%";

        //emit updateProgress(this->_copier->checkProgress());
        emit updateProgress(_progress);
    }
}
void CopierHandler::copyCanceled(QString id, QString path, QString discId, bool parentalControl)
{
    qDebug() << "CopierHandler::stopCopyDisc()";
    _discDataList.clear();
    checkProgress();
    if(timer.isActive())    timer.stop();
    if(_proc!=NULL){
        qDebug() << "_proc->kill()";
        _proc->kill();
    }
    emit canceled(id,path,discId,parentalControl);
    EjectVolume(this->_copier->getDriveLetter().at(0).toAscii());
}
void CopierHandler::readyReadStandardOutput()
{
    qDebug() << "CopierHandler::readyReadStandardOutput()";
    QProcess *proc = (QProcess*)sender();
    QByteArray stdoutput = proc->readAllStandardOutput();
    qDebug() << "StandardOutput = "<<stdoutput;
//    QString output(stdoutput);
//    QStringList list = output.split("%");
//    QStringListIterator it(list);
//    while (it.hasNext())
//    {
//        QString item =it.next().trimmed();
//        bool ok;
//        float progress = item.toFloat(&ok);
//        if(ok)
//        {
//          _progress = progress;
//        }

//    }
}

void CopierHandler::processFinished(int exitCode, QProcess::ExitStatus exitStatus )
{
    qDebug() << "CopierHandler::processFinished";
    qDebug()<<"ExitCode: "<<exitCode;
    qDebug()<<"ExitStatus: "<<exitStatus;
    if(exitStatus==QProcess::NormalExit)
    {
        emit finished(_id,this->_copier->getValidFolderName(),_discId,_parentalControl);
        EjectVolume(this->_copier->getDriveLetter().at(0).toAscii());
    }
    else
    {
        this->removeFolder(_destinationPath+ "\\" + this->_copier->getValidFolderName());
    }
    qDebug()<<"delete sender()";
    QProcess *proc = (QProcess*)sender();
    proc->deleteLater();
    qDebug()<<"_proc = NULL";
    _proc = NULL;
    timer.stop();
    qDebug()<<"exit CopierHandler::processFinished";

}

void CopierHandler::startRobocopy(QString id,QString path,QString discId,bool parentalControl)
{
    _id = id;
    _discId = discId;
    _parentalControl = parentalControl;
    //timer.stop();
    qDebug() << "CopierHandler::startRobocopy(QString id,QString path,QString discId,bool parentalControl)";
    _discDataList.clear();
    checkProgress();
    QString destinationPath = _destinationPath+ "\\" + this->_copier->getValidFolderName();
    qDebug()<<"Copiando ["<<path<<"] a ["<<destinationPath<<"]";
    _proc= new QProcess;
    connect(_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
    connect(_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));

    QStringList args;
    //args<< path << destinationPath<<"/MIR"<<"/Z"<<"/MOVE";
    args<< path << destinationPath<<"/B"<<"/MIR"<<"/Z";
    _proc->start( "robocopy", args );
}

void CopierHandler::copyFinished(QString id,QString path,QString discId,bool parentalControl)
{
    _id = id;
    _discId = discId;
    _parentalControl = parentalControl;
    timer.stop();
    qDebug() << "CopierHandler::copyFinished: Emitting finished(id,path)"<<id<<" "<<path;
    _discDataList.clear();
    checkProgress();    
    QString destinationPath = _destinationPath+ "\\" + this->_copier->getValidFolderName();
    qDebug()<<"Moviendo ["<<path<<"] a ["<<destinationPath<<"]";
    _proc= new QProcess;
    connect(_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
    connect(_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readyReadStandardOutput()));

    QStringList args;
    //args<< path << destinationPath<<"/MIR"<<"/Z"<<"/MOVE";
    args<< path << destinationPath<<"/MIR"<<"/Z";
    _proc->start( "robocopy", args );
}
void CopierHandler::setDestinatinPath(QString value)
{
    _destinationPath = value;
}

QString CopierHandler::getDestinatinPath()
{
    return _destinationPath;
}
